﻿<!DOCTYPE html>
<html ng-app="minimal">
<head>
  <meta charset="UTF-8">
  <title>Minimal GoJS Sample with AngularJS</title>
  <meta name="description" content="Interactive diagram implemented by GoJS using AngularJS (version 1), including a diagram directive and model binding." />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Copyright 1998-2019 by Northwoods Software Corporation. -->

  <script src="../release/go.js"></script>
  <script src="../assets/js/goSamples.js"></script>  <!-- this is only for the GoJS Samples framework -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.2/angular.min.js"></script>
  <script id="code">
    angular.module('minimal', [])
      .directive('goDiagram', function() {
        return {
          restrict: 'E',
          template: '<div></div>',  // just an empty DIV element
          replace: true,
          scope: { model: '=goModel' },
          link: function(scope, element, attrs) {

            if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this

            var $ = go.GraphObject.make;
            var diagram =  // create a Diagram for the given HTML DIV element
              $(go.Diagram, element[0],
                {
                  nodeTemplate: $(go.Node, "Auto",
                    new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
                    $(go.Shape, "RoundedRectangle", new go.Binding("fill", "color"),
                      {
                        portId: "", cursor: "pointer", strokeWidth: 0,
                        fromLinkable: true, toLinkable: true,
                        fromLinkableSelfNode: true, toLinkableSelfNode: true,
                        fromLinkableDuplicates: true, toLinkableDuplicates: true
                      }),
                    $(go.TextBlock, { margin: 8, editable: true },
                      new go.Binding("text", "name").makeTwoWay())
                  ),
                  linkTemplate: $(go.Link,
                    { relinkableFrom: true, relinkableTo: true },
                    $(go.Shape),
                    $(go.Shape, { toArrow: "Standard", stroke: null, strokeWidth: 0 })
                  ),
                  "ModelChanged": updateAngular,
                  "ChangedSelection": updateSelection,
                  "undoManager.isEnabled": true
                });

            // whenever a GoJS transaction has finished modifying the model, update all Angular bindings
            function updateAngular(e) {
              if (e.isTransactionFinished) {
                scope.$apply();
              }
            }

            // update the Angular model when the Diagram.selection changes
            function updateSelection(e) {
              diagram.model.selectedNodeData = null;
              var it = diagram.selection.iterator;
              while (it.next()) {
                var selnode = it.value;
                // ignore a selected link or a deleted node
                if (selnode instanceof go.Node && selnode.data !== null) {
                  diagram.model.selectedNodeData = selnode.data;
                  break;
                }
              }
              scope.$apply();
            }

            // notice when the value of "model" changes: update the Diagram.model
            scope.$watch("model", function(newmodel) {
              var oldmodel = diagram.model;
              if (oldmodel !== newmodel) {
                diagram.removeDiagramListener("ChangedSelection", updateSelection);
                diagram.model = newmodel;
                diagram.addDiagramListener("ChangedSelection", updateSelection);
              }
            });

            scope.$watch("model.selectedNodeData.name", function(newname) {
              if (!diagram.model.selectedNodeData) return;
              // disable recursive updates
              diagram.removeModelChangedListener(updateAngular);
              // change the name
              diagram.startTransaction("change name");
              // the data property has already been modified, so setDataProperty would have no effect
              var node = diagram.findNodeForData(diagram.model.selectedNodeData);
              if (node !== null) node.updateTargetBindings("name");
              diagram.commitTransaction("change name");
              // re-enable normal updates
              diagram.addModelChangedListener(updateAngular);
            });
          }
        };
      })
      .controller('MinimalCtrl', function($scope) {
        $scope.model = new go.GraphLinksModel(
          [
            { key: 1, name: "Alpha", color: "lightblue" },
            { key: 2, name: "Beta", color: "orange" },
            { key: 3, name: "Gamma", color: "lightgreen" },
            { key: 4, name: "Delta", color: "pink" }
          ],
          [
            { from: 1, to: 2 },
            { from: 1, to: 3 },
            { from: 2, to: 2 },
            { from: 3, to: 4 },
            { from: 4, to: 1 }
          ]);

        $scope.model.selectedNodeData = null;

        $scope.replaceModel = function() {
          $scope.model = new go.GraphLinksModel(
            [
              { key: 11, name: "zeta", color: "red" },
              { key: 12, name: "eta", color: "green" }
            ],
            [
              { from: 11, to: 12 }
            ]
          );
        }
      });
  </script>
</head>
<body ng-controller="MinimalCtrl"> <!-- only needed for the goSamples framework -->
<div id="sample">
  <!-- a go-diagram element referring to the model, originally written as: -->
  <!-- &lt;go-diagram go-model="model" style="border: solid 1px blue; width:100%; height:400px"&gt;&lt;/go-diagram&gt; -->
  <go-diagram go-model="model" style="border: solid 1px black; width:100%; height:400px"></go-diagram>
  Number of node data: {{model.nodeDataArray.length}}
  <br />
  Alpha node location: {{model.findNodeDataForKey(1).loc}}
  <br />
  Selected node: {{model.selectedNodeData.key}}  <input type="text" ng-model="model.selectedNodeData.name"></input>
  <br />
  Number of link data: {{model.linkDataArray.length}}
  <p class="box bg-info">
  This is an AngularJS v1 sample.  For a minimal Angular v4+ project, see the <code>../projects/angular-basic/</code> subdirectory.
  </p>
  <p>
  This defines an <a href="https://angularjs.org/">AngularJS</a> directive for creating a <b>GoJS</b> <a>Diagram</a> with certain properties.
  It also sets up a controller holding a <a>GraphLinksModel</a> that is passed
  to the <b>go-diagram</b> element via the <b>go-model</b> attribute.
  </p>
  <p>
  Note that the above bindings are updated automatically as the user moves the "Alpha" node,
  copies or deletes Parts in the Diagram, reconnects the Link from "Alpha" to "Beta", or performs an undo or redo.
  </p>
  <p>
  You can also replace the <a>Diagram.model</a> just by setting the "model" property on the $scope,
  since the "goDiagram" directive watches that property for changes.
  </p>
  <button ng-click="replaceModel()">Replace Model</button>
  <p>
  Please note that the source code shown here for the HTML shows the expanded DIV element produced by AngularJS and other modified elements,
  not <code>&lt;go-diagram go-model="model" style=...&gt;&lt;/go-diagram&gt;</code> and &#123; &#123; &#125; &#125; bindings as originally written.
  </p>
</div>
</body>
</html>